package com.smit.icastplus.ssdp;

import com.smit.utils.LogUtil;

import java.io.IOException;
import java.net.DatagramPacket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SSDP管理类
 */
public final class SSDPManager {
    private static final String TAG = SSDPManager.class.getSimpleName();
    private static final int SSDP_CALLBACK_CONNECT_FAIL = 0;
    private static final int SSDP_CALLBACK_HOST_GET = 1;
    private static final int SSDP_CALLBACK_HOST_LIMIT = 2;

    private int curSSDPStatus = -1;
    private SSDPInterface ssdpInterface = null;
    private String serverAddress = "";
    private boolean stopSearchFlag = false;
    private boolean stopHeartBeatFlag = false;
    private ExecutorService executorService = null;
    private String ipFromServer = null;
//    private DVBAdapter dvbAdapter = DVBAdapter.getInstance();

    private final Runnable startSearchRunnable = new Runnable() {
        @Override
        public void run() {
            LogUtil.debug(TAG, " startSearchRunnable start~~~~~~~~~~~");
            String receiveStr;
            DatagramPacket datagramPacket = null;
            SSDPMultiCastSocket ssdpMultiCastSocket = null; //用来多播的socket
            SSDPDatagramSocket ssdpDatagramSocket = null; //用来单播的socket
            String searchMsgString = SSDPMsg.getSearchMessage();

            while (!stopSearchFlag) {
                if (ssdpMultiCastSocket == null || ssdpDatagramSocket == null) {
                    try {
                        ssdpMultiCastSocket = new SSDPMultiCastSocket();
                        ssdpDatagramSocket = new SSDPDatagramSocket();
                    } catch (IOException e) {
                        LogUtil.debug(TAG, "1--SSDP ERROR:" + e.getMessage());
                        ssdpMultiCastSocket = null;
                        ssdpDatagramSocket = null;

                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            LogUtil.debug(TAG, "InterruptedException error1:" + e1.getMessage());
                            break;
                        }

                        continue;
                    }
                }

                try {
                    ssdpMultiCastSocket.sendMessage(searchMsgString); //先多播search
                    datagramPacket = ssdpDatagramSocket.receiveMessage(); //接收server返回信息
                    receiveStr = new String(datagramPacket.getData(), "UTF-8").trim();
                    LogUtil.debug(TAG, "receiveStr:" + receiveStr);
                } catch (IOException e) {
                    receiveStr = "";
                    LogUtil.debug(TAG, "2--SSDP ERROR:" + e.getMessage());
                }

                if (receiveStr.contains(SSDPConstants.NTS_LIMIT)) //server连接达到上限
                {
                    doCallBack(SSDP_CALLBACK_HOST_LIMIT);
                } else if (receiveStr.contains(SSDPConstants.ICAST_FLAG)) {
                    serverAddress = datagramPacket.getAddress().getHostAddress();
                    ipFromServer = getIpFromServer(receiveStr);
                    LogUtil.debug(TAG, " ipFromServer:" + ipFromServer + " serverAddress:" + serverAddress);
                    startHeartBeat(); //启动心跳
                    break;
                } else {
                    doCallBack(SSDP_CALLBACK_CONNECT_FAIL);
                }
            }

            LogUtil.debug(TAG, " startSearchRunnable close~~~~~~~~~~~");
            if (ssdpMultiCastSocket != null) {
                ssdpMultiCastSocket.close();
            }

            if (ssdpDatagramSocket != null) {
                ssdpDatagramSocket.closeSocket();
            }
        }
    };

    private final Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            LogUtil.debug(TAG, "start heartBeatRunnable~~~~~~~");
//            String localIpAddress = NetUtil.getLocalIpAddress();
//            dvbAdapter.initGrpcData(serverAddress, ipFromServer);
            doCallBack(SSDP_CALLBACK_HOST_GET);

            while (!stopHeartBeatFlag) {
                if (!doClientKeepConnect()) {
                    doHeartBeatFail();
                    break;
                }

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    LogUtil.debug(TAG, "sleep--InterruptedException:" + e.getMessage());
                    break;
                }
            }

            LogUtil.debug(TAG, " heartBeatRunnable close~~~~~~~~~~~");
        }
    };

    private SSDPManager() {
        executorService = Executors.newCachedThreadPool();
    }

    /**
     * @return 获取SSDPManager实例
     */
    public static SSDPManager getInstance() {
        return SSDPManagerHolder.instance;
    }

    /**
     * @param callback SSDPInterface实例
     */
    public void setCallback(SSDPInterface callback) {
        this.ssdpInterface = callback;
    }

    /**
     * 释放资源
     */
    public void releaseResource() {
        LogUtil.debug(TAG, "releaseResource~~~~");
        stopSearchFlag = true;
        stopHeartBeatFlag = true;
        executorService.shutdownNow();

        executorService = null;
        ssdpInterface = null;
//        dvbAdapter = null;
    }

    /**
     * 启动SSDP线程
     */
    public void startSSDP() {
        if (executorService != null && !executorService.isShutdown()) {
            executorService.execute(startSearchRunnable);
        }
    }

    private void startHeartBeat() {
        if (executorService != null && !executorService.isShutdown()) {
            stopHeartBeatFlag = false;
            executorService.execute(heartBeatRunnable);
        }
    }

    private boolean doClientKeepConnect() {
        try {
//            if (dvbAdapter != null && !dvbAdapter.isGrpcShutDown()) {
//                dvbAdapter.clientKeepConnect(ipFromServer);
//            }
        } catch (Exception e) {
            LogUtil.debug(TAG, " clientKeepConnect error:" + e.getMessage());
            return false;
        }

        return true;
    }

    private void doHeartBeatFail() {
//        if (dvbAdapter != null && !dvbAdapter.isGrpcShutDown()) {
//            doCallBack(SSDP_CALLBACK_CONNECT_FAIL);
//            startSSDP();
//            dvbAdapter.shutDownGrpc();
//        }
    }

    private void doCallBack(int type) {
        LogUtil.debug(TAG, "type:" + type + " curSSDPStatus:" + curSSDPStatus);
        if (curSSDPStatus == type) {
            return;
        }

        curSSDPStatus = type;

        if (ssdpInterface != null) {
            switch (curSSDPStatus) {
                case SSDP_CALLBACK_CONNECT_FAIL:
                    ssdpInterface.connectFail();
                    break;
                case SSDP_CALLBACK_HOST_GET:
                    ssdpInterface.hostGet(serverAddress);
                    break;
                case SSDP_CALLBACK_HOST_LIMIT:
                    ssdpInterface.hostLimit();
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * server那端传来的，目的确保ssdp ip和 grpc传的ip一致,server那端用此作为设备的标识
     *
     * @param str 消息字符串
     * @return ip
     */
    private String getIpFromServer(String str) {
        Pattern pattern = Pattern.compile("https://.*/");
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            String matcherStr = matcher.group();
            return matcherStr.substring("https://".length(), matcherStr.length() - 1);
        }

        return null;
    }

    private static class SSDPManagerHolder {
        private static SSDPManager instance = new SSDPManager();
    }
}
